using System;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Text;
using EntityKit.Runtime;

namespace EntityKit.Editor
{
    public class ExcelEditorWindow : EditorWindow
    {
        /// <summary>
        /// Excel文件列表
        /// </summary>
        private List<string> mAllExcelList = new List<string>();
        
        /// <summary>
        /// 存储每个Excel文件对应的Toggle状态
        /// </summary>
        private Dictionary<string, bool> mToggleStates = new Dictionary<string, bool>();
        
        /// <summary>
        /// 选中的Excel文件列表
        /// </summary>
        private List<string> mSelectExcelList = new List<string>();

        /// <summary>
        /// 滚动窗口初始位置
        /// </summary>
        private Vector2 mScrollPos;

        private ExcelPathSettingConfig mExcelPathSettingConfig;

        // 样式定义
        private GUIStyle m_BoxStyle;
        private GUIStyle m_HeaderStyle;
        private GUIStyle m_ButtonStyle;
        private GUIStyle m_SmallButtonStyle;
        private GUIStyle m_LabelStyle;
        private GUIStyle m_FilePathStyle;
        private GUIStyle m_FileNameStyle;
        private GUIStyle m_TitleStyle;
        private GUIStyle m_SectionHeaderStyle;
        private GUIStyle m_SelectedFileStyle;
        
        private const string FOLDOUT_OPEN_PREFIX = "▼ ";
        private const string FOLDOUT_CLOSED_PREFIX = "▶ ";
        private bool showPathsSection = true;
        private bool showFilesSection = true;

        public static void ShowExcelTools()
        {
            ExcelEditorWindow window = EditorWindow.GetWindow<ExcelEditorWindow>();
            // 使用Unity内置的表格图标替代不存在的ExcelIcon
            window.titleContent.image = EditorGUIUtility.IconContent("d_SpriteAtlasAsset Icon").image;
            window.titleContent.text = "Excel Processing Tool";
            window.minSize = new Vector2(500, 500);
            window.maxSize = new Vector2(Screen.currentResolution.width, Screen.currentResolution.height);
            window.Show();
        }

        private void OnEnable()
        {
            mSelectExcelList.Clear();
            mToggleStates.Clear();
            LoadOrCreateExcelPathSettingConfig();
            if (mExcelPathSettingConfig != null)
                RefreshAllXlsxFiles(mExcelPathSettingConfig.ExcelFilePath);
        }

        private void InitStyles()
        {
            if (m_BoxStyle == null)
            {
                m_BoxStyle = new GUIStyle(EditorStyles.helpBox);
                m_BoxStyle.padding = new RectOffset(10, 10, 10, 10);
                m_BoxStyle.margin = new RectOffset(0, 0, 5, 5);
            }

            if (m_HeaderStyle == null)
            {
                m_HeaderStyle = new GUIStyle(EditorStyles.largeLabel);
                m_HeaderStyle.fontStyle = FontStyle.Bold;
                m_HeaderStyle.fontSize = 16;
                m_HeaderStyle.margin = new RectOffset(0, 0, 5, 10);
                m_HeaderStyle.normal.textColor = EditorGUIUtility.isProSkin ? new Color(0.8f, 0.8f, 0.8f) : new Color(0.2f, 0.2f, 0.2f);
            }

            if (m_TitleStyle == null)
            {
                m_TitleStyle = new GUIStyle(EditorStyles.largeLabel);
                m_TitleStyle.fontSize = 18;
                m_TitleStyle.fontStyle = FontStyle.Bold;
                m_TitleStyle.alignment = TextAnchor.MiddleCenter;
                m_TitleStyle.normal.textColor = EditorGUIUtility.isProSkin ? new Color(0.8f, 0.8f, 0.8f) : new Color(0.2f, 0.2f, 0.2f);
            }

            if (m_SectionHeaderStyle == null)
            {
                m_SectionHeaderStyle = new GUIStyle(EditorStyles.foldout);
                m_SectionHeaderStyle.fontStyle = FontStyle.Bold;
                m_SectionHeaderStyle.fontSize = 14;
                m_SectionHeaderStyle.margin = new RectOffset(0, 0, 5, 10);
            }

            if (m_ButtonStyle == null)
            {
                m_ButtonStyle = new GUIStyle(GUI.skin.button);
                m_ButtonStyle.padding = new RectOffset(10, 10, 10, 10);
                m_ButtonStyle.margin = new RectOffset(5, 5, 5, 5);
            }

            if (m_SmallButtonStyle == null)
            {
                m_SmallButtonStyle = new GUIStyle(GUI.skin.button);
                m_SmallButtonStyle.padding = new RectOffset(5, 5, 5, 5);
                m_SmallButtonStyle.margin = new RectOffset(2, 2, 2, 2);
                m_SmallButtonStyle.fontSize = 11;
            }

            if (m_LabelStyle == null)
            {
                m_LabelStyle = new GUIStyle(EditorStyles.label);
                m_LabelStyle.margin = new RectOffset(0, 0, 2, 2);
                m_LabelStyle.fontSize = 11;
            }

            if (m_FilePathStyle == null)
            {
                m_FilePathStyle = new GUIStyle(EditorStyles.textField);
                m_FilePathStyle.padding = new RectOffset(5, 5, 5, 5);
                m_FilePathStyle.wordWrap = true;
            }
            
            if (m_FileNameStyle == null)
            {
                m_FileNameStyle = new GUIStyle(EditorStyles.label);
                m_FileNameStyle.padding = new RectOffset(5, 5, 6, 6);
                m_FileNameStyle.wordWrap = false;
                m_FileNameStyle.clipping = TextClipping.Clip;
                m_FileNameStyle.alignment = TextAnchor.MiddleLeft;
                m_FileNameStyle.stretchWidth = true;
            }
            
            if (m_SelectedFileStyle == null)
            {
                m_SelectedFileStyle = new GUIStyle(EditorStyles.label);
                m_SelectedFileStyle.padding = new RectOffset(5, 5, 6, 6);
                m_SelectedFileStyle.wordWrap = false;
                m_SelectedFileStyle.clipping = TextClipping.Clip;
                m_SelectedFileStyle.alignment = TextAnchor.MiddleLeft;
                m_SelectedFileStyle.stretchWidth = true;
                m_SelectedFileStyle.fontStyle = FontStyle.Bold;
                m_SelectedFileStyle.normal.textColor = EditorGUIUtility.isProSkin ? new Color(0.7f, 0.9f, 0.7f) : new Color(0.1f, 0.5f, 0.1f);
            }
        }

        private void OnGUI()
        {
            InitStyles();
            
            DrawHeader();
            DrawPathsSection();
            DrawFileListSection();
            DrawActionButtons();
        }

        private void DrawHeader()
        {
            GUILayout.Space(10);
            EditorGUILayout.LabelField("Excel Processing Tool", m_TitleStyle);
            GUILayout.Space(10);
        }

        private void DrawPathsSection()
        {
            GUILayout.BeginVertical(m_BoxStyle);
            showPathsSection = EditorGUILayout.Foldout(showPathsSection, 
                new GUIContent((showPathsSection ? FOLDOUT_OPEN_PREFIX : FOLDOUT_CLOSED_PREFIX) + "Configuration Paths"), 
                true, m_SectionHeaderStyle);
            
            if (showPathsSection)
            {
                EditorGUILayout.Space(5);
                DrawExcelFilePath();
                DrawJsonOutputPath();
                DrawCodeOutputPath();
            }
            
            GUILayout.EndVertical();
            EditorGUILayout.Space(10);
        }

        private void DrawFileListSection()
        {
            GUILayout.BeginVertical(m_BoxStyle);
            
            showFilesSection = EditorGUILayout.Foldout(showFilesSection, 
                new GUIContent((showFilesSection ? FOLDOUT_OPEN_PREFIX : FOLDOUT_CLOSED_PREFIX) + $"Excel Files List ({mSelectExcelList.Count} selected)"), 
                true, m_SectionHeaderStyle);
            
            if (showFilesSection)
            {
                EditorGUILayout.Space(5);

                // 添加操作按钮行
                GUILayout.BeginHorizontal();
                if (GUILayout.Button("Select All", m_SmallButtonStyle, GUILayout.Width(80)))
                    SelectAllExcelFiles(true);
                    
                if (GUILayout.Button("Deselect All", m_SmallButtonStyle, GUILayout.Width(80)))
                    SelectAllExcelFiles(false);
                    
                if (GUILayout.Button("Refresh", m_SmallButtonStyle, GUILayout.Width(80)))
                    RefreshAllXlsxFiles(mExcelPathSettingConfig.ExcelFilePath);
                GUILayout.EndHorizontal();

                EditorGUILayout.Space(5);

                mScrollPos = EditorGUILayout.BeginScrollView(mScrollPos, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
                if (mAllExcelList.Count == 0)
                {
                    EditorGUILayout.HelpBox("No Excel files found in the specified directory. Please check the path or add .xlsx files.", MessageType.Info);
                }
                else
                {
                    foreach (string excelName in mAllExcelList)
                    {
                        DrawFileItem(excelName);
                    }
                }
                EditorGUILayout.EndScrollView();
            }

            GUILayout.EndVertical();
            GUILayout.Space(10);
        }

        private void DrawFileItem(string excelName)
        {
            EditorGUILayout.BeginHorizontal(m_BoxStyle);
            
            // 检查文件是否存在
            if (!File.Exists(excelName))
            {
                EditorGUILayout.HelpBox($"File not found: {Path.GetFileName(excelName)}", MessageType.Warning);
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.Space(2);
                return;
            }
            
            if (!mToggleStates.ContainsKey(excelName))
                mToggleStates[excelName] = false;

            bool newToggleState = GUILayout.Toggle(mToggleStates[excelName], "", GUILayout.Width(20));

            if (newToggleState != mToggleStates[excelName])
            {
                mToggleStates[excelName] = newToggleState;
                if (newToggleState)
                {
                    mSelectExcelList.Add(excelName);
                }
                else
                {
                    mSelectExcelList.Remove(excelName);
                }
            }

            string fileName = Path.GetFileName(excelName);
            GUIStyle fileNameStyle = mToggleStates[excelName] ? m_SelectedFileStyle : m_FileNameStyle;
            EditorGUILayout.LabelField(fileName, fileNameStyle, GUILayout.ExpandWidth(true), GUILayout.Height(22));

            if (GUILayout.Button("Gen Json", m_SmallButtonStyle, GUILayout.Width(80), GUILayout.Height(20)))
            {
                GenJson(new List<string>() { excelName });
                ShowNotification(new GUIContent("JSON generated successfully!"));
            }

            if (GUILayout.Button("Gen Code", m_SmallButtonStyle, GUILayout.Width(80), GUILayout.Height(20)))
            {
                GenCode(new List<string>() { excelName });
                ShowNotification(new GUIContent("Code generated successfully!"));
            }

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space(2);
        }

        private void DrawActionButtons()
        {
            EditorGUILayout.BeginVertical(m_BoxStyle);
            EditorGUILayout.Space(5);
            
            EditorGUILayout.BeginHorizontal();
            
            if (GUILayout.Button("Generate JSON for Selected", m_ButtonStyle))
            {
                if (mSelectExcelList.Count > 0)
                {
                    GenJson(mSelectExcelList);
                    ShowNotification(new GUIContent($"Generated JSON for {mSelectExcelList.Count} file(s)!"));
                }
                else
                {
                    ShowNotification(new GUIContent("No files selected!"));
                }
            }

            if (GUILayout.Button("Generate Code for Selected", m_ButtonStyle))
            {
                if (mSelectExcelList.Count > 0)
                {
                    GenCode(mSelectExcelList);
                    ShowNotification(new GUIContent($"Generated code for {mSelectExcelList.Count} file(s)!"));
                }
                else
                {
                    ShowNotification(new GUIContent("No files selected!"));
                }
            }

            if (GUILayout.Button("Generate Both for Selected", m_ButtonStyle))
            {
                if (mSelectExcelList.Count > 0)
                {
                    GenCode(mSelectExcelList);
                    GenJson(mSelectExcelList);
                    ShowNotification(new GUIContent($"Generated code and JSON for {mSelectExcelList.Count} file(s)!"));
                }
                else
                {
                    ShowNotification(new GUIContent("No files selected!"));
                }
            }

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndVertical();
            GUILayout.Space(10);
        }

        /// <summary>
        /// 生成Json
        /// </summary>
        /// <param name="excelNames"></param>
        /// <returns></returns>
        private void GenJson(List<string> excelNames)
        {
            var ret = EditorUtility.DisplayDialog("Confirm", @"Are you sure you want to generate JSON files?", "Yes", "No");

            if (!ret) return;
            foreach (var excelName in excelNames)
            {
                try
                {
                    ExcelConverter excel = new ExcelConverter(excelName);

                    Encoding encoding = Encoding.GetEncoding("utf-8");
                    string fileName = Path.GetFileNameWithoutExtension(excelName) + ".json";
                    FileHelper.CreateDirectoryIfNotExists(mExcelPathSettingConfig.Excel2JsonPath);
                    var outputConfigPath = Path.Combine(mExcelPathSettingConfig.Excel2JsonPath, fileName);
                    excel.ConvertToJson(outputConfigPath, encoding);
                }
                catch (Exception ex)
                {
                    Debug.LogError($"Error processing file {excelName}: {ex.Message}");
                    EditorUtility.DisplayDialog("Error", $"Error processing file {Path.GetFileName(excelName)}: {ex.Message}", "OK");
                }
            }

            AssetDatabase.Refresh();
        }

        /// <summary>
        /// 生成代码
        /// </summary>
        /// <param name="excelNames"></param>
        /// <returns></returns>
        private void GenCode(List<string> excelNames)
        {
            var ret = EditorUtility.DisplayDialog("Confirm", @"Are you sure you want to generate code files?", "Yes", "No");
            if (ret)
            {
                try
                {
                    ExcelCodeGenerator.GenerateCode(excelNames, mExcelPathSettingConfig.Excel2CodePath);
                }
                catch (Exception ex)
                {
                    Debug.LogError($"Error generating code: {ex.Message}");
                    EditorUtility.DisplayDialog("Error", $"Error generating code: {ex.Message}", "OK");
                }
            }
        }

        /// <summary>
        /// 绘制带拖拽功能的路径选择控件
        /// </summary>
        /// <param name="label">标签</param>
        /// <param name="path">当前路径</param>
        /// <param name="onPathSelected">路径选择回调</param>
        /// <param name="refreshAction">刷新操作（可选）</param>
        private void DrawPathSelector(string label, string path, Action<string> onPathSelected, Action refreshAction = null)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField(label, GUILayout.Width(80));
            
            // 创建一个只读的路径显示区域，但仍支持复制
            Rect dropArea = GUILayoutUtility.GetRect(0.0f, 30.0f, GUILayout.ExpandWidth(true));
            // 使用GUI.TextField但设置为只读模式，确保可以复制
            GUI.enabled = false;
            GUI.TextField(dropArea, path, m_FilePathStyle);
            GUI.enabled = true;
            
            // 处理拖拽事件
            if (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform)
            {
                if (dropArea.Contains(Event.current.mousePosition))
                {
                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                    
                    if (Event.current.type == EventType.DragPerform)
                    {
                        DragAndDrop.AcceptDrag();
                        
                        foreach (string draggedPath in DragAndDrop.paths)
                        {
                            string fullPath = Path.GetFullPath(draggedPath);
                            string assetsPath = Path.GetFullPath(Application.dataPath);
                            
                            if (fullPath.StartsWith(assetsPath) || fullPath + Path.DirectorySeparatorChar == assetsPath)
                            {
                                onPathSelected(fullPath);
                                refreshAction?.Invoke();
                                Event.current.Use();
                                GUI.changed = true;
                                break;
                            }
                        }
                    }
                    
                    Event.current.Use();
                }
            }
            
            string buttonLabel = "Browse";
            string panelTitle = "Select Folder";
            if (GUILayout.Button(buttonLabel, m_SmallButtonStyle, GUILayout.Width(60), GUILayout.Height(30)))
            {
                string selectedPath = EditorUtility.OpenFolderPanel(panelTitle, path, "");
                if (!string.IsNullOrEmpty(selectedPath))
                {
                    onPathSelected(selectedPath);
                    refreshAction?.Invoke();
                }
            }
            
            // 添加复制路径按钮
            if (GUILayout.Button("Copy", m_SmallButtonStyle, GUILayout.Width(50), GUILayout.Height(30)))
            {
                if (!string.IsNullOrEmpty(path))
                {
                    EditorGUIUtility.systemCopyBuffer = path;
                    ShowNotification(new GUIContent("Path copied to clipboard!"));
                }
            }
            
            // 添加打开路径按钮
            if (GUILayout.Button("Open", m_SmallButtonStyle, GUILayout.Width(50), GUILayout.Height(30)))
            {
                if (Directory.Exists(path))
                {
                    EditorUtility.RevealInFinder(path);
                }
                else
                {
                    EditorUtility.DisplayDialog("Path Not Found", "The specified path does not exist.", "OK");
                }
            }
            
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space(5);
        }

        /// <summary>
        /// Excel文件路径
        /// </summary>
        private void DrawExcelFilePath()
        {
            DrawPathSelector("Excel Path:", mExcelPathSettingConfig.ExcelFilePath, path => {
                    mExcelPathSettingConfig.ExcelFilePath = path;
                    EditorUtility.SetDirty(mExcelPathSettingConfig);
                    AssetDatabase.SaveAssets();
                },
                () => RefreshAllXlsxFiles(mExcelPathSettingConfig.ExcelFilePath)
            );
        }

        /// <summary>
        /// Json输出路径
        /// </summary>
        private void DrawJsonOutputPath()
        {
            DrawPathSelector("JSON Path:", mExcelPathSettingConfig.Excel2JsonPath, path => {
                    mExcelPathSettingConfig.Excel2JsonPath = path;
                    EditorUtility.SetDirty(mExcelPathSettingConfig);
                    AssetDatabase.SaveAssets();
                }
            );
        }

        /// <summary>
        /// Code输出路径
        /// </summary>
        private void DrawCodeOutputPath()
        {
            DrawPathSelector("Code Path:", mExcelPathSettingConfig.Excel2CodePath, path => {
                    mExcelPathSettingConfig.Excel2CodePath = path;
                    EditorUtility.SetDirty(mExcelPathSettingConfig);
                    AssetDatabase.SaveAssets();
                }
            );
        }

        /// <summary>
        /// 获取第一层的所有Excel文件
        /// </summary>
        /// <param name="directoryPath"></param>
        private void RefreshAllXlsxFiles(string directoryPath)
        {
            mAllExcelList.Clear();
            if (!string.IsNullOrEmpty(directoryPath) && Directory.Exists(directoryPath))
            {
                mAllExcelList.AddRange(Directory.GetFiles(directoryPath, "*.xlsx", SearchOption.AllDirectories));
            }
        }
        
        private void LoadOrCreateExcelPathSettingConfig()
        {
            mExcelPathSettingConfig = ExcelPathSettingConfig.LoadOrCreateExcelPathSettingConfig();
        }

        /// <summary>
        /// 全选或取消全选所有Excel文件
        /// </summary>
        /// <param name="select">true为全选，false为取消全选</param>
        private void SelectAllExcelFiles(bool select)
        {
            mSelectExcelList.Clear();
            mToggleStates.Clear();
            
            foreach (string excelName in mAllExcelList)
            {
                mToggleStates[excelName] = select;
                if (select)
                {
                    mSelectExcelList.Add(excelName);
                }
            }
            
            Repaint();
        }
    }
}